#include "typedef.h"
#include "os_tick.h"
#include "work.h"
#include "key_rotate_driver.h"
#include "key_rotate.h"

enum
{
    PIN_L_L = 0x0,
    PIN_H_L = 0x2,
    PIN_L_H = 0x1,
    PIN_H_H = 0x3,
};

typedef enum
{
    ROTATE_STEP_IDLE = 0,
    ROTATE_STEP_WAIT_PROCESS,
} E_ROTATE_STEP;

struct key_rotate_bsp_s
{
    SysTick_t time;
    void(*function)(E_ROTATE index, E_ROTATE_TYPE type);
};

struct key_rotate_s
{
    E_ROTATE_STEP step;
    u16 step_time;
    u8 last_status;
};

static struct key_rotate_s rotate[KEY_ROTATE_MAX] = {{ROTATE_STEP_IDLE}};
static struct key_rotate_bsp_s key_rotate_bsp={0};

//旋转完整过程：H_H,H_L,L_L,L_H,H_H 或 H_H,L_H,L_L,H_L,H_H
static void key_rotate_check_1ms(E_ROTATE index )
{
    u8 pin_status;
    E_ROTATE_TYPE rotate_status = ROTATE_PRESS_IDLE;
    struct key_rotate_s *key = &rotate[index];

    pin_status = key_rotate_get_pin1_state(index);
    pin_status <<= 1;
    pin_status |= key_rotate_get_pin2_state(index);
    pin_status &= PIN_H_H;

    switch (key->step)
    {
        case ROTATE_STEP_IDLE:
            if ((pin_status == PIN_H_L) || (pin_status == PIN_L_H))
            {
                key->step = ROTATE_STEP_WAIT_PROCESS;
                key->step_time = 0;
                key->last_status = pin_status;
            }
            break;
        case ROTATE_STEP_WAIT_PROCESS:
            if(key->last_status == pin_status)
                key->step_time++;
            else if (pin_status == PIN_L_L)
                key->step_time++;
            else if(pin_status == ((~key->last_status)&PIN_H_H))
                key->step_time++;
            else if ((pin_status == PIN_H_H) && (key->step_time>=Tnms(1)))
            {
                rotate_status = (key->last_status == PIN_H_L) ? ROTATE_PRESS_LEFT : ROTATE_PRESS_RIGHT;
                key->step = ROTATE_STEP_IDLE;
                if(key_rotate_bsp.function)
                    key_rotate_bsp.function(index,rotate_status);
            }
        break;
        default:
            key->step = ROTATE_STEP_IDLE;
        break;
    }
}

void key_rotate_worktick(unsigned int data)
{
    if(0 == systick_get_difference_assign(&key_rotate_bsp.time,Tnms(1)))
		return ;
    for(int i=0; i<KEY_ROTATE_MAX; i++)
        key_rotate_check_1ms((E_ROTATE)i);
}

void key_rotate_init(void(*function)(E_ROTATE , E_ROTATE_TYPE))
{
    for(int i=0; i<KEY_ROTATE_MAX; i++)
        key_rotate_gpio_init((E_ROTATE)i);

    key_rotate_bsp.function =function;

    work_add_tail(key_rotate_worktick,0);
}

